package com.jeasonzhao.commons.inplacecache;

import java.util.LinkedHashMap;
import java.util.Iterator;

/**
 * LRU (least recently used) cache.
 *
 * <p>
 * Items are added to the cache as they are accessed; when the cache is full, the least recently used item is ejected.
 * This type of cache is typically implemented as a linked list, so that an item in cache, when it is accessed again,
 * can be moved back up to the head of the queue; items are ejected from the tail of the queue. Cache access overhead
 * is again constant time. This algorithm is simple and fast, and it has a significant advantage over FIFO in being
 * able to adapt somewhat to the data access pattern; frequently used items are less likely to be
 * ejected from the cache. The main disadvantage is that it can still get filled up with items that are
 * unlikely to be reaccessed soon; in particular, it can become useless in the face of scanning type accesses.
 * Nonetheless, this is by far the most frequently used caching algorithm.<br>
 * Summary for LRU: fast, adaptive, not scan resistant.
 */
public class LRUCache<K,V> extends AbstractCacheMap<K,V>
{

    public LRUCache(int cacheSize)
    {
        this(cacheSize,0);
    }

    /**
     * Creates a new LRU cache.
     */
    public LRUCache(int cacheSize,long timeout)
    {
        super(cacheSize,timeout,new LinkedHashMap<K,CacheObject<K,V>>(cacheSize + 1,1.0f,true)
//        {
//            @Override
//            protected boolean removeEldestEntry(Map.Entry eldest)
//            {
//                return size() > LRUCache.this.getCacheSize();
//            }
//        }
        );
    }

    @Override
    public int prune()
    {
        if(isPruneExpiredActive() == false)
        {
            return 0;
        }
        int count = 0;
        Iterator<CacheObject<K,V>> values = null == this.getCacheMap() ? null
            : this.getCacheMap().values().iterator();
        while(null != values && values.hasNext())
        {
            CacheObject<K,V> co = values.next();
            if(co.isExpired() == true)
            {
                values.remove();
                count++;
            }
        }
        return count;
    }
}
